<template>
  <div class="file-upload">
    <!-- 拖拽上传区域 -->
    <div
      class="upload-area"
      :class="{
        'drag-over': isDragOver,
        'uploading': isUploading,
        'disabled': disabled
      }"
      @drop="handleDrop"
      @dragover="handleDragOver"
      @dragenter="handleDragEnter"
      @dragleave="handleDragLeave"
      @click="triggerFileInput"
    >
      <div class="upload-content">
        <div class="upload-icon">
          <svg v-if="!isUploading" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
            <polyline points="7,10 12,15 17,10"/>
            <line x1="12" y1="15" x2="12" y2="3"/>
          </svg>
          <div v-else class="loading-spinner">
            <div class="spinner"></div>
          </div>
        </div>
        
        <div class="upload-text">
          <h3 v-if="!isUploading">{{ uploadText }}</h3>
          <h3 v-else>正在上传...</h3>
          <p v-if="!isUploading">支持 {{ supportedFormats.join(', ') }} 格式</p>
          <p v-else>{{ uploadProgress }}%</p>
        </div>
      </div>
      
      <!-- 进度条 -->
      <div v-if="isUploading" class="progress-bar">
        <div class="progress-fill" :style="{ width: uploadProgress + '%' }"></div>
      </div>
    </div>
    
    <!-- 隐藏的文件输入 -->
    <input
      ref="fileInput"
      type="file"
      :accept="acceptedTypes"
      :multiple="multiple"
      @change="handleFileSelect"
      style="display: none"
    />
    
    <!-- 文件列表 -->
    <div v-if="selectedFiles.length > 0" class="file-list">
      <h4>已选择的文件</h4>
      <div class="file-items">
        <div
          v-for="(file, index) in selectedFiles"
          :key="index"
          class="file-item"
        >
          <div class="file-info">
            <div class="file-icon">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/>
              </svg>
            </div>
            <div class="file-details">
              <span class="file-name">{{ file.name }}</span>
              <span class="file-size">{{ formatFileSize(file.size) }}</span>
            </div>
          </div>
          <button
            class="remove-file"
            @click="removeFile(index)"
            :disabled="isUploading"
          >
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <line x1="18" y1="6" x2="6" y2="18"/>
              <line x1="6" y1="6" x2="18" y2="18"/>
            </svg>
          </button>
        </div>
      </div>
    </div>
    
    <!-- 输出格式选择 -->
    <div v-if="selectedFiles.length > 0 && !isUploading" class="format-selection">
      <h4>选择输出格式</h4>
      <div class="format-options">
        <label
          v-for="format in outputFormats"
          :key="format.value"
          class="format-option"
        >
          <input
            type="radio"
            :value="format.value"
            v-model="selectedFormat"
            name="output-format"
          />
          <span class="format-label">
            <span class="format-name">{{ format.name }}</span>
            <span class="format-desc">{{ format.description }}</span>
          </span>
        </label>
      </div>
    </div>
    
    <!-- 上传按钮 -->
    <div v-if="selectedFiles.length > 0 && !isUploading" class="upload-actions">
      <button
        class="upload-btn primary"
        @click="startUpload"
        :disabled="!selectedFormat"
      >
        开始转换
      </button>
      <button
        class="upload-btn secondary"
        @click="clearFiles"
      >
        清空文件
      </button>
    </div>
    
    <!-- 错误信息 -->
    <div v-if="errorMessage" class="error-message">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <circle cx="12" cy="12" r="10"/>
        <line x1="15" y1="9" x2="9" y2="15"/>
        <line x1="9" y1="9" x2="15" y2="15"/>
      </svg>
      <span>{{ errorMessage }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useTaskStore } from '@/stores/task'
import { apiService } from '@/services/api'

interface OutputFormat {
  value: string
  name: string
  description: string
}

interface Props {
  multiple?: boolean
  disabled?: boolean
  maxFileSize?: number // MB
  supportedFormats?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  multiple: true,
  disabled: false,
  maxFileSize: 50,
  supportedFormats: () => ['MD', 'TXT']
})

const emit = defineEmits<{
  upload: [files: File[], format: string]
  error: [message: string]
}>()

// 响应式数据
const fileInput = ref<HTMLInputElement>()
const selectedFiles = ref<File[]>([])
const selectedFormat = ref<string>('')
const isDragOver = ref(false)
const isUploading = ref(false)
const uploadProgress = ref(0)
const errorMessage = ref('')
const outputFormats = ref<OutputFormat[]>([])

// 任务存储
const taskStore = useTaskStore()

// 计算属性
const acceptedTypes = computed(() => {
  const extensions = props.supportedFormats.map(format => `.${format.toLowerCase()}`)
  return extensions.join(',')
})

const uploadText = computed(() => {
  return props.multiple 
    ? '拖拽文件到此处或点击选择文件'
    : '拖拽文件到此处或点击选择文件'
})

// 生命周期
onMounted(async () => {
  await loadOutputFormats()
})

// 方法
const loadOutputFormats = async () => {
  try {
    // 暂时使用静态数据，后续可以从 API 获取
    outputFormats.value = [
      { value: 'pdf', name: 'PDF', description: '便携式文档格式' },
      { value: 'docx', name: 'DOCX', description: 'Microsoft Word文档' },
      { value: 'html', name: 'HTML', description: '网页格式' },
      { value: 'epub', name: 'EPUB', description: '电子书格式' }
    ]
    selectedFormat.value = 'pdf'
  } catch (error) {
    console.error('加载输出格式失败:', error)
    // 设置默认格式
    outputFormats.value = [
      { value: 'pdf', name: 'PDF', description: '便携式文档格式' },
      { value: 'docx', name: 'DOCX', description: 'Microsoft Word文档' },
      { value: 'html', name: 'HTML', description: '网页格式' }
    ]
    selectedFormat.value = 'pdf'
  }
}

const triggerFileInput = () => {
  if (!props.disabled && !isUploading.value) {
    fileInput.value?.click()
  }
}

const handleFileSelect = (event: Event) => {
  const target = event.target as HTMLInputElement
  if (target.files) {
    addFiles(Array.from(target.files))
  }
}

const handleDrop = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = false
  
  if (props.disabled || isUploading.value) return
  
  const files = event.dataTransfer?.files
  if (files) {
    addFiles(Array.from(files))
  }
}

const handleDragOver = (event: DragEvent) => {
  event.preventDefault()
}

const handleDragEnter = (event: DragEvent) => {
  event.preventDefault()
  if (!props.disabled && !isUploading.value) {
    isDragOver.value = true
  }
}

const handleDragLeave = (event: DragEvent) => {
  event.preventDefault()
  // 只有当离开整个拖拽区域时才设置为false
  if (!event.currentTarget?.contains(event.relatedTarget as Node)) {
    isDragOver.value = false
  }
}

const addFiles = (files: File[]) => {
  errorMessage.value = ''
  
  const validFiles = files.filter(file => {
    // 检查文件类型
    const extension = file.name.split('.').pop()?.toLowerCase()
    if (!extension || !props.supportedFormats.map(f => f.toLowerCase()).includes(extension)) {
      showError(`不支持的文件格式: ${file.name}`)
      return false
    }
    
    // 检查文件大小
    const maxSize = props.maxFileSize * 1024 * 1024 // 转换为字节
    if (file.size > maxSize) {
      showError(`文件过大: ${file.name} (最大 ${props.maxFileSize}MB)`)
      return false
    }
    
    return true
  })
  
  if (props.multiple) {
    selectedFiles.value = [...selectedFiles.value, ...validFiles]
  } else {
    selectedFiles.value = validFiles.slice(0, 1)
  }
}

const removeFile = (index: number) => {
  selectedFiles.value.splice(index, 1)
}

const clearFiles = () => {
  selectedFiles.value = []
  selectedFormat.value = outputFormats.value[0]?.value || ''
  errorMessage.value = ''
}

const startUpload = async () => {
  if (selectedFiles.value.length === 0 || !selectedFormat.value) {
    showError('请选择文件和输出格式')
    return
  }
  
  isUploading.value = true
  uploadProgress.value = 0
  errorMessage.value = ''
  
  try {
    // 创建FormData
    const formData = new FormData()
    selectedFiles.value.forEach(file => {
      formData.append('files', file)
    })
    formData.append('output_format', selectedFormat.value)
    
    // 上传文件
    const response = await apiService.post('/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: (progressEvent) => {
        if (progressEvent.total) {
          uploadProgress.value = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          )
        }
      }
    })
    
    if (response.data.success) {
      // 添加任务到存储
      if (response.data.task_id) {
        await taskStore.addTask({
          id: response.data.task_id,
          filename: selectedFiles.value[0].name,
          status: 'queued',
          output_format: selectedFormat.value,
          created_at: new Date().toISOString(),
          progress: 0
        })
      }
      
      // 触发上传事件
      emit('upload', selectedFiles.value, selectedFormat.value)
      
      // 清空文件
      clearFiles()
    } else {
      showError(response.data.error || '上传失败')
    }
  } catch (error: any) {
    console.error('上传失败:', error)
    showError(error.response?.data?.error || '上传失败，请稍后重试')
  } finally {
    isUploading.value = false
    uploadProgress.value = 0
  }
}

const showError = (message: string) => {
  errorMessage.value = message
  emit('error', message)
  setTimeout(() => {
    errorMessage.value = ''
  }, 5000)
}

const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
</script>

<style scoped>
.file-upload {
  width: 100%;
  max-width: 600px;
  margin: 0 auto;
}

.upload-area {
  border: 2px dashed #d1d5db;
  border-radius: 12px;
  padding: 40px 20px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  background: #fafafa;
  position: relative;
  overflow: hidden;
}

.upload-area:hover {
  border-color: #3b82f6;
  background: #f8faff;
}

.upload-area.drag-over {
  border-color: #3b82f6;
  background: #eff6ff;
  transform: scale(1.02);
}

.upload-area.uploading {
  border-color: #10b981;
  background: #f0fdf4;
  cursor: not-allowed;
}

.upload-area.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.upload-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.upload-icon {
  color: #6b7280;
  transition: color 0.3s ease;
}

.upload-area:hover .upload-icon {
  color: #3b82f6;
}

.loading-spinner {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 48px;
  height: 48px;
}

.spinner {
  width: 32px;
  height: 32px;
  border: 3px solid #e5e7eb;
  border-top: 3px solid #3b82f6;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.upload-text h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #374151;
}

.upload-text p {
  margin: 0;
  font-size: 14px;
  color: #6b7280;
}

.progress-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: #e5e7eb;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #3b82f6, #10b981);
  transition: width 0.3s ease;
}

.file-list {
  margin-top: 24px;
}

.file-list h4 {
  margin: 0 0 12px 0;
  font-size: 16px;
  font-weight: 600;
  color: #374151;
}

.file-items {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px;
  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
}

.file-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.file-icon {
  color: #6b7280;
}

.file-details {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.file-name {
  font-size: 14px;
  font-weight: 500;
  color: #374151;
}

.file-size {
  font-size: 12px;
  color: #6b7280;
}

.remove-file {
  padding: 4px;
  background: none;
  border: none;
  color: #ef4444;
  cursor: pointer;
  border-radius: 4px;
  transition: background-color 0.2s ease;
}

.remove-file:hover {
  background: #fef2f2;
}

.remove-file:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.format-selection {
  margin-top: 24px;
}

.format-selection h4 {
  margin: 0 0 12px 0;
  font-size: 16px;
  font-weight: 600;
  color: #374151;
}

.format-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
}

.format-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px;
  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.format-option:hover {
  border-color: #3b82f6;
  background: #f8faff;
}

.format-option input[type="radio"] {
  margin: 0;
}

.format-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.format-name {
  font-size: 14px;
  font-weight: 500;
  color: #374151;
}

.format-desc {
  font-size: 12px;
  color: #6b7280;
}

.upload-actions {
  margin-top: 24px;
  display: flex;
  gap: 12px;
  justify-content: center;
}

.upload-btn {
  padding: 12px 24px;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
}

.upload-btn.primary {
  background: #3b82f6;
  color: white;
}

.upload-btn.primary:hover {
  background: #2563eb;
}

.upload-btn.primary:disabled {
  background: #9ca3af;
  cursor: not-allowed;
}

.upload-btn.secondary {
  background: #f3f4f6;
  color: #374151;
  border: 1px solid #d1d5db;
}

.upload-btn.secondary:hover {
  background: #e5e7eb;
}

.error-message {
  margin-top: 16px;
  padding: 12px;
  background: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: 8px;
  color: #dc2626;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}

@media (max-width: 640px) {
  .upload-area {
    padding: 24px 16px;
  }
  
  .format-options {
    grid-template-columns: 1fr;
  }
  
  .upload-actions {
    flex-direction: column;
  }
}
</style>